﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EmitMapper;
using EmitMapper.MappingConfiguration;
using EmitMapper.MappingConfiguration.MappingOperations;

namespace Zhj.Community.Infrastructure.Mapper
{
    public class MapperMaster
    {
        /// <summary>
        /// 基本映射
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TEntity2"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static TEntity2 Mapper<TEntity, TEntity2>(object obj) where TEntity : class
        {
            var mapper = ObjectMapperManager.DefaultInstance.GetMapper<TEntity, TEntity2>();
            return mapper.Map(obj as TEntity);
        }

        /// <summary>
        /// 有外键关联，需要映射出外键所带名字
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TEntity2"></typeparam>
        /// <typeparam name="TEntity3"></typeparam>
        /// <param name="obj"></param>
        /// <param name="converter"></param>
        /// <returns></returns>
        public static TEntity2 Mapper<TEntity, TEntity2, TEntity3>(object obj, Func<TEntity3, ICloneable> converter) where TEntity : class
        {
            var mapper = ObjectMapperManager.DefaultInstance.GetMapper<TEntity, TEntity2>(
               new DefaultMapConfig()
               .ConvertUsing(converter)
               );
            return mapper.Map(obj as TEntity);
        }


        /// <summary>
        /// 两个实体之间名字不一致，需要映射。
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TEntity2"></typeparam>
        /// <param name="obj"></param>
        /// <param name="membersMatcher"></param>
        /// <returns></returns>
        public static TEntity2 Mapper<TEntity, TEntity2>(object obj, Func<string, string, bool> membersMatcher) where TEntity : class
        {
            var mapper = ObjectMapperManager.DefaultInstance.GetMapper<TEntity, TEntity2>(
               new DefaultMapConfig()
               .MatchMembers(membersMatcher)
               );

            return mapper.Map(obj as TEntity);
        }

        /// <summary>
        /// 需要对某一个字段进行特殊处理
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TEntity2"></typeparam>
        /// <param name="obj"></param>
        /// <param name="postProcessor"></param>
        /// <returns></returns>
        public static TEntity2 Mapper<TEntity, TEntity2>(object obj, ValuesPostProcessor<TEntity2> postProcessor) where TEntity : class
        {
            var mapper = ObjectMapperManager.DefaultInstance.GetMapper<TEntity, TEntity2>(
                new DefaultMapConfig()
                .PostProcess(postProcessor)
            );
            return mapper.Map(obj as TEntity);
        }

        /// <summary>
        /// 忽略掉某个字段的映射
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TEntity2"></typeparam>
        /// <param name="obj"></param>
        /// <param name="ignoreNames"></param>
        /// <returns></returns>
        public static TEntity2 Mapper<TEntity, TEntity2>(object obj, string[] ignoreNames) where TEntity : class
        {
            var mapper = ObjectMapperManager.DefaultInstance.GetMapper<TEntity, TEntity2>(
                new DefaultMapConfig()
                .IgnoreMembers<TEntity, TEntity2>(ignoreNames)
            );
            return mapper.Map(obj as TEntity);
        }

        /// <summary>
        /// 给空元素赋默认值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TEntity2"></typeparam>
        /// <param name="obj"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static TEntity2 Mapper<TEntity, TEntity2>(object obj, string val) where TEntity : class
        {
            var mapper = ObjectMapperManager.DefaultInstance.GetMapper<TEntity, TEntity2>(
               new DefaultMapConfig()
               //如果日期为空设置为当前时间
               //.NullSubstitution<DateTime?, DateTime>((value) => DateTime.Now)
               //如果string类型为null赋值为“”
               .NullSubstitution<string, string>((value) => val)
           );
            return mapper.Map(obj as TEntity);
        }

    }
}
